#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.append(BASE_DIR)
import model_const

import time
import serial
from bb04p1_fast import time as time_pl
from hw_comm import serial_port
from bb04p1_fast import chip_const
from bb04p1_fast import auto_test_frame as at_frame
from bb04p1_fast import data_handle
from bb04p1_fast.nano_pb import hardware_pb2
from bb04p1_fast.fw import uart_handler as hw_uart
uart_port = None

import configparser

def exe_UART_cmd(comm_bus, case_id, input, expected, slave_bus=None):
    global uart_port
    flag = False
    cmd_para = None
    print(f"{time_pl.get_time()}.....{input}")
    msg, data, cmd_type = hw_uart.uart_handle(None, input)
    # 判断是否需要关闭被测串口
    if 'close' in input:
        if uart_port is not None:
            uart_port.close_port()
            uart_port = None
        return True
    # 发送指令到串口
    if '\\x' in input:
        # 指令中含有需要将数据发送到被测串口的数据
        # 并发送指令
        index = input.rfind(' ')
        cmd_para = input[index + 1:len(input)]
        cmd_para = cmd_para.replace('\\x', '')
        cmd_para = bytes.fromhex(cmd_para)
        comm_bus.sendmsg(msg, True)
        flag = True
    else:
        comm_bus.sendmsg(msg, True)
    # time.sleep(0.1)
    # 判断是否需要打开串口
    config = configparser.ConfigParser()
    config.read('config.py', encoding='utf-8')
    a = config.get('test_uart0_port', 'test_uart0_port')
    b = config.get('test_uart1_port', 'test_uart1_port')
    if 'open' in input:
        addr, baudrate, bytesize, parity, stopbits, mode = hw_uart.uart_parse(cmd_type=cmd_type, data=data)
        if mode == 0:
            if int(baudrate) >= 300:
                if bytesize == serial.EIGHTBITS or bytesize == serial.SEVENBITS:
                    if uart_port is not None:
                        uart_port.close_port()
                    if addr == 0:
                        uart_port = serial_port.Cserial(a,
                                                        baudrate,
                                                        bytesize, parity, stopbits)
                        print(f"{time_pl.get_time()}.....serial 0 is open")
                    elif addr == 1:
                        uart_port = serial_port.Cserial(b,
                                                        baudrate,
                                                        bytesize, parity, stopbits)
                        print(f"{time_pl.get_time()}.....serial 1 is open")
                    else:
                        return False
                    uart_port.setDaemon(True)
                    uart_port.start()
    # 判断是否有期望结果
    if len(expected):
        # 有期望结果
        # 判断是否为回环模式
        if uart_port is None:
            # 回环模式
            time.sleep(0.1)
            msg = time_pl.wait_message_serial_port(comm_bus, "uart", 3)
            typ, message = data_handle.data_decoder(msg)
            if message is None:
                print(f"{time_pl.get_time()}.....uart message is None")
                print(f"{time_pl.get_time()}.....uart is failed")
                return False
            if typ != hardware_pb2.uart:
                print(f"{time_pl.get_time()}.....uart cmd failed")
                return False
            # 根据期望值判断串口获取到的是数据还是uart中断
            if '\\x' in expected:
                # 获取到的为数据
                message = ''.join(message).replace('0', '\\')
                if message != expected:
                    print(f"{time_pl.get_time()}.....message.....{message}")
                    print(f"{time_pl.get_time()}.....uart is failed")
                    return False
                print(f"{time_pl.get_time()}.....uart is exc ok")
                return True
            else:
                # 中断模式
                if message != expected:
                    print(f"{time_pl.get_time()}.....message.....{message}")
                    print(f"{time_pl.get_time()}.....uart is failed")
                    return False
                print(f"{time_pl.get_time()}.....uart exc is ok")
                return True
        else:
            # 不是回环模式
            # 判断是否需要从被测串口发数据
            if flag:
                # 需要从被测串口发数据
                time.sleep(0.05)
                uart_port.sendmsg(cmd_para)
                flag = False
                # time.sleep(0.5)
                msg = time_pl.wait_message_serial_port(comm_bus, "uart", 3)
                typ, message = data_handle.data_decoder(msg)
                if message is None:
                    print(f"{time_pl.get_time()}.....uart is failed message is None")
                    return False
                if typ == hardware_pb2.result:
                    msg = time_pl.wait_message_serial_port(comm_bus, "uart", 3)
                    typ, message = data_handle.data_decoder(msg)
                if typ != hardware_pb2.uart:
                    print(f"{time_pl.get_time()}.....message.....{message}")
                    print(f"{time_pl.get_time()}.....uart is failed.....type.....{typ}")
                    return False
                # 判断返回是数据还是中断
                if '\\x' in expected:
                    # 数据
                    message = ''.join(message).replace('0x', '')
                    expected = expected.replace('\\x', '')
                    if message != expected:
                        print(f"{time_pl.get_time()}.....message.....{message}")
                        print(f"{time_pl.get_time()}.....uart is failed")
                        return False
                    print(f"{time_pl.get_time()}.....uart exc is ok")
                    return True
                else:
                    # 中断
                    if message != expected:
                        print(f"{time_pl.get_time()}.....message.....{message}")
                        print(f"{time_pl.get_time()}.....uart is failed")
                        return False
                    print(f"{time_pl.get_time()}.....uart exc is ok")
                    return True
            else:
                # 不需要从被测串口发数据
                # 判断是否为中断
                if '\\x' in expected:
                    # 数据
                    time.sleep(0.05)
                    msg = time_pl.wait_message_serial_port(uart_port, "uart", 3)
                    message = data_handle.bytelist2str(msg)
                    if message is None:
                        print(f"{time_pl.get_time()}.....uart is failed")
                        return False
                    if expected not in message:
                        print(f"{time_pl.get_time()}.....message.....{message}")
                        print(f"{time_pl.get_time()}.....uart is failed")
                        return False
                    print(f"{time_pl.get_time()}.....uart exc is ok")
                    return True
                else:
                    # 中断
                    msg = time_pl.wait_message_serial_port(comm_bus, "uart", 3)
                    typ, message = data_handle.data_decoder(msg)
                    if message is None:
                        print(f"{time_pl.get_time()}.....uart is failed")
                        return False
                    if typ == hardware_pb2.result:
                        msg = time_pl.wait_message_serial_port(comm_bus, "uart", 3)
                        typ, message = data_handle.data_decoder(msg)
                    if typ != hardware_pb2.uart:
                        print(f"{time_pl.get_time()}.....uart is failed")
                        return False
                    if message != expected:
                        print(f"{time_pl.get_time()}.....message.....{message}")
                        print(f"{time_pl.get_time()}.....uart is failed")
                        return False
                    print(f"{time_pl.get_time()}.....uart exc is ok")
                    return True
    # 无期望结果
    if uart_port is not None and flag:
        uart_port.sendmsg(cmd_para)
        # time.sleep(0.1)
    for i in range(0, 5):
        msg = time_pl.wait_message_serial_port(comm_bus, "uart", 3)
        typ, message = data_handle.data_decoder(msg)
        if typ == hardware_pb2.result:
            if message == chip_const.BB04P1_FW_CMD_REPLY.GENERAL_CMD_OK.value:
                print(f"{time_pl.get_time()}.....uart cmd OK")
                return True
        continue
    print(f"{time_pl.get_time()}.....uart cmd failed")
    return False


def exe_UART_cmd_rtt(comm_bus, case_id, input, expected):
    global uart_port
    flag = False
    cmd_para = None
    print(f"{time_pl.get_time()}.....{input}")
    msg, data, cmd_type = hw_uart.uart_handle(None, input)
    # 判断是否需要关闭被测串口
    if 'close' in input:
        if uart_port is not None:
            uart_port.close_port()
            uart_port = None
        return True
    # 发送指令到串口
    if '\\x' in input:
        # 指令中含有需要将数据发送到被测串口的数据
        # 并发送指令
        index = input.rfind(' ')
        cmd_para = input[index + 1:len(input)]
        cmd_para = cmd_para.replace('\\x', '')
        cmd_para = bytes.fromhex(cmd_para)
        comm_bus.sendmsg(msg, True)
        flag = True
    else:
        comm_bus.sendmsg(msg, True)
    # time.sleep(0.1)
    # 判断是否需要打开串口
    if 'open' in input:
        addr, baudrate, bytesize, parity, stopbits, mode = hw_uart.uart_parse(cmd_type=cmd_type, data=data)
        if mode == 0:
            if int(baudrate) >= 300:
                if bytesize == serial.EIGHTBITS or bytesize == serial.SEVENBITS:
                    if uart_port is not None:
                        uart_port.close_port()
                    if addr == 0:
                        uart_port = serial_port.Cserial(model_const.SERIAL_PORT_CONFIG.test_uart0_port.value,
                                                        baudrate,
                                                        bytesize, parity, stopbits)
                        print(f"{time_pl.get_time()}.....serial 0 is open")
                    elif addr == 1:
                        uart_port = serial_port.Cserial(model_const.SERIAL_PORT_CONFIG.test_uart1_port.value,
                                                        baudrate,
                                                        bytesize, parity, stopbits)
                        print(f"{time_pl.get_time()}.....serial 1 is open")
                    else:
                        return False
                    uart_port.setDaemon(True)
                    uart_port.start()
    # 判断是否有期望结果
    if len(expected):
        # 有期望结果
        # 判断是否为回环模式
        if uart_port is None:
            # 回环模式
            time.sleep(0.1)
            msg = time_pl.wait_message(comm_bus, "uart", 3)
            message = data_handle.msg_decoder(msg[0], msg[1])
            if message is None:
                print(f"{time_pl.get_time()}.....uart message is None")
                print(f"{time_pl.get_time()}.....uart is failed")
                return False
            if msg[0] != hardware_pb2.uart:
                print(f"{time_pl.get_time()}.....uart cmd failed")
                return False
            # 根据期望值判断串口获取到的是数据还是uart中断
            if '\\x' in expected:
                # 获取到的为数据
                message = ''.join(message).replace('0', '\\')
                if message != expected:
                    print(f"{time_pl.get_time()}.....message.....{message}")
                    print(f"{time_pl.get_time()}.....uart is failed")
                    return False
                print(f"{time_pl.get_time()}.....uart is exc ok")
                return True
            else:
                # 中断模式
                if message != expected:
                    print(f"{time_pl.get_time()}.....message.....{message}")
                    print(f"{time_pl.get_time()}.....uart is failed")
                    return False
                print(f"{time_pl.get_time()}.....uart exc is ok")
                return True
        else:
            # 不是回环模式
            # 判断是否需要从被测串口发数据
            if flag:
                # 需要从被测串口发数据
                time.sleep(0.05)
                uart_port.sendmsg(cmd_para)
                flag = False
                msg = time_pl.wait_message(comm_bus, "uart", 3)
                message = data_handle.msg_decoder(msg[0], msg[1])
                if message is None:
                    print(f"{time_pl.get_time()}.....uart is failed message is None")
                    return False
                if msg[0] == hardware_pb2.result:
                    msg = time_pl.wait_message(comm_bus, "uart", 3)
                    message = data_handle.msg_decoder(msg[0], msg[1])
                if msg[0] != hardware_pb2.uart:
                    print(f"{time_pl.get_time()}.....message.....{message}")
                    print(f"{time_pl.get_time()}.....uart is failed.....type.....{msg[0]}")
                    return False
                # 判断返回是数据还是中断
                if '\\x' in expected:
                    # 数据
                    message = ''.join(message).replace('0x', '')
                    expected = expected.replace('\\x', '')
                    if message != expected:
                        print(f"{time_pl.get_time()}.....message.....{message}")
                        print(f"{time_pl.get_time()}.....uart is failed")
                        return False
                    print(f"{time_pl.get_time()}.....uart exc is ok")
                    return True
                else:
                    # 中断
                    if message != expected:
                        print(f"{time_pl.get_time()}.....message.....{message}")
                        print(f"{time_pl.get_time()}.....uart is failed")
                        return False
                    print(f"{time_pl.get_time()}.....uart exc is ok")
                    return True
            else:
                # 不需要从被测串口发数据
                # 判断是否为中断
                if '\\x' in expected:
                    # 数据
                    time.sleep(0.05)
                    msg = time_pl.wait_message_serial_port(uart_port, "uart", 3)
                    message = data_handle.bytelist2str(msg)
                    if message is None:
                        print(f"{time_pl.get_time()}.....uart is failed")
                        return False
                    if expected not in message:
                        print(f"{time_pl.get_time()}.....message.....{message}")
                        print(f"{time_pl.get_time()}.....uart is failed")
                        return False
                    print(f"{time_pl.get_time()}.....uart exc is ok")
                    return True
                else:
                    msg = time_pl.wait_message(comm_bus, "uart", 3)
                    message = data_handle.msg_decoder(msg[0], msg[1])
                    if message is None:
                        print(f"{time_pl.get_time()}.....uart is failed")
                        return False
                    if msg[0] == hardware_pb2.result:
                        msg = time_pl.wait_message(comm_bus, "uart", 3)
                        message = data_handle.msg_decoder(msg[0], msg[1])
                    if msg[0] != hardware_pb2.uart:
                        print(f"{time_pl.get_time()}.....uart is failed")
                        return False
                    if message != expected:
                        print(f"{time_pl.get_time()}.....message.....{message}")
                        print(f"{time_pl.get_time()}.....uart is failed")
                        return False
                    print(f"{time_pl.get_time()}.....uart exc is ok")
                    return True
    # 无期望结果
    if uart_port is not None and flag:
        uart_port.sendmsg(cmd_para)
        time.sleep(0.05)
    for i in range(0, 5):
        msg = time_pl.wait_message(comm_bus, "uart", 3)
        message = data_handle.msg_decoder(msg[0], msg[1])
        if msg[0] == hardware_pb2.result:
            if message == chip_const.BB04P1_FW_CMD_REPLY.GENERAL_CMD_OK.value:
                print(f"{time_pl.get_time()}.....uart cmd OK")
                return True
        continue
    print(f"{time_pl.get_time()}.....uart cmd failed")
    return False


if __name__ == '__main__':
    hw_comm_bus = at_frame._init_hw_bus(model_const.COMMUNICATION_HW_BUS_TYPE.SERIAL_PORT)  # SERIAL_PORT #JLINK_RTT
    hw_comm_bus.clear()
    testlink_comm = at_frame._init_testlink_comm(chip_const.TESTLINK_CONFIG.testlink_server_url.value,
                                                 chip_const.TESTLINK_CONFIG.testlink_server_key.value,
                                                 'BB04P1',
                                                 'I2S mode1-2',
                                                 'v1.1')
    at_frame.Run_AutoTest(hw_comm_bus, testlink_comm)
    print("done!")
    at_frame.test_result(testlink_comm)
